package org.ailoli.aixiang.present

import android.content.Context
import android.hardware.usb.*
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Observer
import io.reactivex.rxjava3.disposables.Disposable
import org.ailoli.aixiang.base.BasePresenter
import org.ailoli.aixiang.bean.BatteryBean
import org.ailoli.aixiang.bean.CabinetBean
import org.ailoli.aixiang.bean.GetQrCodeUrlBean
import org.ailoli.aixiang.bean.LoginBean
import org.ailoli.aixiang.constants.SystemConstants
import org.ailoli.aixiang.contract.MainContract
import org.ailoli.aixiang.data.BatteryData
import org.ailoli.aixiang.model.MainModel
import org.ailoli.aixiang.net.RxScheduler
import org.ailoli.aixiang.utils.CabinetUtils
import org.ailoli.aixiang.utils.Utils
import java.io.File
import java.nio.ByteBuffer
import java.nio.charset.Charset
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
import kotlin.collections.ArrayList


class MainPresenter : BasePresenter<MainContract.View?>(), MainContract.Presenter {
    private val model: MainContract.Model
    var serialPortDispose: Disposable? = null
    private var mDeviceConnection: UsbDeviceConnection? = null
    private var usbEpOut: UsbEndpoint? = null
    private var usbEpIn: UsbEndpoint? = null
    private var manager: UsbManager? = null
    private var usbDevice: UsbDevice? = null
    private var updateFlag: Boolean = false
    private var cabinetBatteryList: ArrayList<BatteryBean>? = null
    private var cabinetLockList: CabinetBean? = null

    override fun login(username: String, password: String) {
        //View是否绑定 如果没有绑定，就不执行网络请求
        if (!isViewAttached) return
        model.login(username, password)
            ?.compose(RxScheduler().Obs_io_main())
            ?.to(mView!!.bindAutoDispose()) //解决内存泄漏
            ?.subscribe(object : Observer<LoginBean?> {
                override fun onSubscribe(d: Disposable?) {

                }

                override fun onNext(t: LoginBean?) {
                    Log.e("token:", t!!.access_token)
                    mView!!.loginCallBack(t)
//                    RetrofitClient.
                }

                override fun onError(e: Throwable?) {
                }

                override fun onComplete() {
                }

            })
    }

    override fun getQrCodeUrl(cabinetId: String) {
        //View是否绑定 如果没有绑定，就不执行网络请求
        if (!isViewAttached) return
        model.getQrCodeUrl(cabinetId)
            ?.compose(RxScheduler().Obs_io_main())
            ?.to(mView?.bindAutoDispose())
            ?.subscribe(object : Observer<GetQrCodeUrlBean> {
                override fun onSubscribe(d: Disposable?) {

                }

                override fun onNext(t: GetQrCodeUrlBean?) {
                    if (t!!.result.equals("success")) {
                        mView!!.setQrCodeUrl(t.content)

                    }
                }

                override fun onError(e: Throwable?) {
                    Log.e("e", e.toString())
                }

                override fun onComplete() {
                }

            })
    }

    override fun getAllSerialPort(): Array<String>? {
        val Serial_Ports_number: MutableList<String> = ArrayList()
        var type: Array<String>? = null
        val file = File("/dev/")
        try {
            val fs: Array<File> = file.listFiles()
            for (f in fs) {
                if (f.getName().contains("tty")) {
                    Serial_Ports_number.add(f.getName())
                }
            }
        } catch (e: IllegalStateException) {
            return Serial_Ports_number.toTypedArray()
        }

        type = Serial_Ports_number.toTypedArray()
        Log.e("serialport_type", type.toString())
        return type
    }

    override fun sendDataToSerialPort() {
        Observable.interval(3, TimeUnit.SECONDS)
            .compose(RxScheduler().Obs_io_main())
            .subscribe(object : Observer<Long> {
                override fun onSubscribe(d: Disposable?) {
                    serialPortDispose = d
                }

                override fun onNext(t: Long?) {
                }

                override fun onError(e: Throwable?) {
                    serialPortDispose!!.dispose()
                }

                override fun onComplete() {
                    serialPortDispose!!.dispose()
                }

            })
    }

    override fun initUsb(context: Context) {
        val systemService = context.getSystemService(Context.USB_SERVICE)
        manager =
            context.getSystemService(AppCompatActivity.USB_SERVICE) as UsbManager
        val deviceList = manager!!.deviceList
        for (item in deviceList) {
            if ((item.value.productId.toString()
                    .equals(SystemConstants.DEVICE_P_ID) && item.value.vendorId.toString()
                    .equals(SystemConstants.DEVICE_V_ID))
            ) {
                usbDevice = item.value
                Log.e("读写权限：", manager!!.hasPermission(usbDevice).toString())
                mDeviceConnection = manager!!.openDevice(usbDevice)
                mDeviceConnection!!.claimInterface(usbDevice!!.getInterface(0), true)
                mDeviceConnection!!.claimInterface(usbDevice!!.getInterface(1), true)
                usbDevice!!.getInterface(0)
                for (index in 0 until usbDevice!!.interfaceCount) {
                    val intf = usbDevice!!.getInterface(index)
                    for (i in 0 until usbDevice!!.getInterface(index).endpointCount) {
                        val ep: UsbEndpoint = intf.getEndpoint(i)
                        if (ep.direction == UsbConstants.USB_DIR_OUT) {
                            usbEpOut = ep // 针对主机而言，从主机 输出到设备,获取到 bulk的输出端点 对象
                        }
                        if (ep.direction == UsbConstants.USB_DIR_IN) {
                            usbEpIn = ep // 针对主机而言，从设备 输出到主机 ,获取到 bulk的输入端点 对象
                        }
                    }
                }
            }
        }
    }

    override fun sendDataToUsb(context: Context) {
    }

    override fun getBatteryInfoByBoxId(context: Context, boxId: Int): ByteArray {
        val byteArray = CabinetUtils.getB8Commond(boxId)
        if (mDeviceConnection == null) return byteArrayOf()
        // 发送数据
        mDeviceConnection!!.bulkTransfer(
            usbEpOut,
            byteArray,
            byteArray.size,
            5000
        )
        return getUsbData(24)
    }

    override fun updateAllBattery(context: Context, batteryList: ArrayList<BatteryBean>) {
        Observable.interval(3, TimeUnit.SECONDS)
            .compose(RxScheduler().Obs_io_main())
            .subscribe(object : Observer<Long> {
                override fun onSubscribe(d: Disposable?) {
                }

                override fun onNext(t: Long?) {
                    if (!updateFlag) {
                        cabinetBatteryList = ArrayList<BatteryBean>()
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        cabinetBatteryList!!.add(BatteryBean(0, BatteryData(0, false)))
                        for ((index, value) in batteryList.withIndex()) {
                            updateFlag = true
                            // 返回的数据做截取，总长度为（5 + 18 + 1）= 24
                            Log.e("开始获取" + (index + 1).toString(), "的电池信息")
                            val batteryInfo = getBatteryInfoByBoxId(context, index + 1)
//                            val batteryInfo: ByteArray by lazy {
//                                getBatteryInfoByBoxId(context, index + 1)
//                            }
                            Log.e((index + 1).toString() + "获取到的为：", Utils.ByteArrToHex(batteryInfo).toString())
                            Log.e("完成获取" + (index + 1).toString(), "的电池信息")
                            // 校验数据帧头是否为 55 55
                            var batteryBean: BatteryBean? = BatteryBean(index, null)
                            try {
                                val header1 =  batteryInfo[SystemConstants.DATA_HEADER_1_POSITION]
                                if ((batteryInfo[SystemConstants.DATA_HEADER_1_POSITION].toString().equals(SystemConstants.DATA_HEADER_1_BYTE)
                                            &&
                                            batteryInfo[SystemConstants.DATA_HEADER_2_POSITION].toString().equals(SystemConstants.DATA_HEADER_2_BYTE))) {
                                    Log.e("可以匹配的二进制", batteryInfo[0].toString())
                                    Log.e((index + 1).toString() + "号电池信息：", Utils.ByteArrToHex(batteryInfo).toString())
                                    val soc = Utils.Byte2Hex(batteryInfo[(SystemConstants.DATA_HEADER_SIZE + SystemConstants.DATA_SOC_POSITION) - 1])
                                        .toString()
                                    val batteryIndex = Utils.Byte2Hex(batteryInfo[2])
                                    if (!soc.equals(SystemConstants.DATA_NORMAL_HEX)){
                                        batteryBean = BatteryBean(index, BatteryData(Utils.HexToInt(soc), false))
                                    }
                                    cabinetBatteryList!!.set(batteryIndex!!.toInt() - 1,batteryBean!!)
                                } else {
                                    cabinetBatteryList!!.set(index,batteryBean!!)
                                    Log.e("不匹配的二进制", batteryInfo.toString())
                                }
                            } catch (e: IndexOutOfBoundsException){
                                Log.e("出错了", e.toString())
                            } catch (e: Exception) {
                                Log.e("出错了", e.toString())
                            } catch (e: ArrayIndexOutOfBoundsException) {
                                Log.e("出错了", e.toString())
                            }
//                            TimeUnit.MILLISECONDS.sleep(500)
//                            sleep
                        }
                        mView!!.onOneBatteryComplete(cabinetBatteryList!!)
                        updateFlag = false
                    }
                }

                override fun onError(e: Throwable?) {
                }

                override fun onComplete() {
                }

            })
    }

    override fun openDoor() {
        val byteArray = CabinetUtils.getOepnDoorCommond(1)
        // 发送数据
        try {
            mDeviceConnection!!.bulkTransfer(
                usbEpOut,
                byteArray,
                byteArray.size,
                5000
            )
            Log.e("开门数据：", Utils.ByteArrToHex(getUsbData(24)).toString())
        } catch (e: KotlinNullPointerException) {
            Log.e("开门", "失败")
        }

    }

    override fun closeDoor() {
        val byteArray = CabinetUtils.getCloseDoorCommond(1)
        try {
            // 发送数据
            mDeviceConnection!!.bulkTransfer(
                usbEpOut,
                byteArray,
                byteArray.size,
                5000
            )
            Log.e("关门数据：", Utils.ByteArrToHex(getUsbData(24)).toString())
        } catch (e: KotlinNullPointerException) {
            Log.e("关门", "失败")
        }
    }

    override fun updateAllBox(context: Context) {
        for ((index, value) in cabinetBatteryList!!.withIndex()) {

        }
    }

    fun getUsbData(totalSize: Int): ByteArray {
        // 发送完毕开始接收数据
        val outMax = usbEpOut!!.maxPacketSize
        val inMax = usbEpIn!!.maxPacketSize
        // 定义缓冲区
        val byteBuffer: ByteBuffer = ByteBuffer.allocate(inMax)
        val usbRequest = UsbRequest()
        usbRequest.initialize(mDeviceConnection, usbEpIn)
        usbRequest.queue(byteBuffer, inMax)
        if (mDeviceConnection!!.requestWait() === usbRequest) {
            val retData = Utils.ByteArrToHex(
                byteBuffer.array(),
                0,
                byteBuffer.array().size
            ).toString()
            return byteBuffer.array().slice(IntRange(0,totalSize)).toByteArray()
        }
        return byteArrayOf()
    }

    init {
        model = MainModel()
    }
}